package com.baizhi.cmfz.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * This is a Class.
 *
 * @author zhanglh
 * @date 2019/09/20
 */
@Configuration
@Aspect
@Slf4j
public class CacheAspect {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 添加缓存
     * 1.判断查询的数据缓存中是否存在
     * 2.没有，查询数据并将数据放入缓存
     * 3.有，直接把缓存中的结果返回
     * 运用环绕增强 放行操作，获取方法执行的返回值
     */
    @Around("@annotation(com.baizhi.cmfz.annotation.AddCacheAnnotation)")
    public Object addCache(ProceedingJoinPoint joinPoint) throws Throwable {
        //获取类名
        String className = joinPoint.getTarget().getClass().getName();
        //获取方法名+形参的值
        StringBuilder stringBuilder = new StringBuilder();
        String methodName = joinPoint.getSignature().getName();
        stringBuilder.append(methodName);
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            stringBuilder.append(arg);
        }
        String hashKey = stringBuilder.toString();
        //判断要得到的数据是否在缓存中
        HashOperations hashOperations = redisTemplate.opsForHash();
        Object result = hashOperations.get(className, hashKey);
        if (result != null) {
            //有 返回结果
            log.debug("从缓存中获取");
            return result;
        }
        //没有 查询数据并存在缓存中
        result = joinPoint.proceed();
        Map<String, Object> map = new HashMap<>();
        map.put(hashKey, result);
        hashOperations.putAll(className, map);
        //设置失效时间 expire 参数1：要设置的key 参数2：时间参数 参数3：时间单位
        redisTemplate.expire(className, 1, TimeUnit.MINUTES);
        log.debug("从数据库中查询并存在缓存");
        return result;
    }

    /**
     * 删除缓存
     */
    @Before("@annotation(com.baizhi.cmfz.annotation.DeleteCacheAnnotation)")
    public void deleteCache(JoinPoint joinPoint) {
        //清除缓存
        //获取类名
        String className = joinPoint.getTarget().getClass().getName();
        log.debug("删除 " + className + " 的缓存");
        //删除
        redisTemplate.delete(className);
    }
}
